package com.yang.design.behavior.observe.example2;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 事件处理类
 * 角色：被观察者
 * 作用：1.状态维护（LotteryResult,这里没有维护在这里）
 *      2.观察者维护（成员变量listeners和subscribe，unsubscribe方法）
 *      3.通知观察者（notify方法）
 */
public class EventManager {

    //将map的key设置成一个枚举类型(内部枚举，和内部类一样),即事件的类型
    public enum EventType{
        MQ,MESSAGE
    }

    //监听器集合
    //key是Enum<EventType>,泛型是EventType,就是EventType枚举中的MQ或者MESSAGE等常量（后期还可以加类型，只需要加常量），它们本质上是Enum类型的实例
    //value是List<EventListener>,用list是为了方便扩展,比如mq可以扩展多个监听类（即观察者）
    Map<Enum<EventType>, List<EventListener>> listeners = new HashMap<>();
    //即被观察者维护， 存储对应所有观察者

    //构造方法，初始化观察者
    public EventManager(Enum<EventType>... operations) {
        for (Enum<EventType> operation : operations) {
            this.listeners.put(operation,new ArrayList<>());
        }
    }
    /*
    它接收可变参数（...表示可变参数），参数类型是Enum<EventType>，
    意味着可以传入一个或多个基于EventType枚举类型的实例（也就是EventType枚举中的具体常量）。
    在构造方法内部，通过循环遍历传入的这些枚举实例，将每个枚举实例作为键，
    初始化一个空的ArrayList作为值，放入到listeners这个映射中。这样就完成了对每种传入的事件类型对应的监听器列表的初始化，
    为后续添加监听器以及触发事件做好了准备。
     */

    //下面的三个方法依次对应的是 添加观察者，删除观察者，和通知观察者

    /**
     * 订阅
     * @param eventType 事件类型
     * @param listener 监听
     */
    public void subscribe(Enum<EventType> eventType,EventListener listener){
        List<EventListener> list = listeners.get(eventType);
        list.add(listener);
    }

    /**
     * 取消订阅
     * @param eventType 事件类型
     * @param listener 监听
     */
    public void unsubscribe(Enum<EventType> eventType,EventListener listener){
        List<EventListener> list = listeners.get(eventType);
        list.remove(listener);
    }

    /**
     * 通知
     * @param eventType 事件类型
     * @param result
     */
    public void notify(Enum<EventType> eventType, LotteryResult result){
        List<EventListener> list = listeners.get(eventType);
        for (EventListener listener : list) {
            listener.doEvent(result);
        }

    }

}
